#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/configfs.h>
#include <linux/kernel.h>
#include <linux/kobject.h>

struct kobject *mykobject01;
struct kobject *mykobject02;
struct kset *mykset;
struct kobj_type mytype;

// 定义一个回调函数，返回kset的名称
const char *myname(struct kset *kset, struct kobject *kobj)
{
    return "my_kset";
};

// 定义一个回调函数，处理kset的uevent事件
int myevent(struct kset *kset, struct kobject *kobj, struct kobj_uevent_env *env)
{
    printk("myevent  fasong     add_uevent_var");
    add_uevent_var(env, "MYDEVICE=%s,sn=%s", "fangchen", "SN00000000001");
    return 0;
};

// 定义一个回调函数，用于过滤kset中的kobject
int myfilter(struct kset *kset, struct kobject *kobj)
{
    if (strcmp(kobj->name, "mykobject01") == 0)
    {
        printk("myfilter    mykobject01   can  not  fasong ");

        return 0; // 返回0表示通过过滤
    }
    else
    {
        return 1; // 返回1表示过滤掉
    }
};

struct kset_uevent_ops my_uevent_ops = {
    .filter = myfilter,
    .uevent = myevent,
    .name = myname,
};

// 模块的初始化函数
static int mykobj_init(void)
{
    int ret;

    // 创建并添加一个kset
    mykset = kset_create_and_add("mykset", &my_uevent_ops, NULL);

    // 分配并初始化一个kobject
    mykobject01 = kzalloc(sizeof(struct kobject), GFP_KERNEL);
    mykobject01->kset = mykset;

    // 初始化并添加kobject到kset
    ret = kobject_init_and_add(mykobject01, &mytype, NULL, "%s", "mykobject01");

    // 分配并初始化一个kobject
    mykobject02 = kzalloc(sizeof(struct kobject), GFP_KERNEL);
    mykobject02->kset = mykset;

    // 初始化并添加kobject到kset
    ret = kobject_init_and_add(mykobject02, &mytype, NULL, "%s", "mykobject02");

    // 触发一个uevent事件，表示mykobject01的属性发生了变化
    ret = kobject_uevent(mykobject01, KOBJ_CHANGE);
    // 触发一个uevent事件，表示mykobject02被添加
    ret = kobject_uevent(mykobject02, KOBJ_ADD);

    return 0;
}

// 模块退出函数
static void mykobj_exit(void)
{
    // 释放kobject
    kobject_put(mykobject01);
    kobject_put(mykobject02);
    kset_unregister(mykset);
}

module_init(mykobj_init); // 指定模块的初始化函数
module_exit(mykobj_exit); // 指定模块的退出函数

MODULE_LICENSE("GPL");     // 模块使用的许可证
MODULE_AUTHOR("fangchen"); // 模块的作者